import {
  HttpException,
  Inject,
  Injectable,
  HttpStatus,
  BadRequestException,
} from '@nestjs/common';
import { RegisterUserDto } from './dto/register-user.dto';
import { User } from './entities/user.entity';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, Like } from 'typeorm';
import { RedisService } from 'src/redis/redis.service';
import { md5 } from 'src/utils';
import { Role } from './entities/role.entity';
import { Permission } from './entities/permission.entity';
import { LoginUserDto } from './dto/login-user.dto';
import { UpdateUserPasswordDto } from './dto/update-user-password.dto';
import { UpdateUserDto } from './dto/update-user.dto';
import { LoginUserVo } from './vo/login-user.vo';
@Injectable()
export class UserService {
  @InjectRepository(User)
  private readonly userRepository: Repository<User>;

  @InjectRepository(Role)
  private readonly roleRepository: Repository<Role>;

  @InjectRepository(Permission)
  private readonly permissionRepository: Repository<Permission>;

  @Inject(RedisService)
  private readonly redisService: RedisService;

  async register(registerUser: RegisterUserDto) {
    console.log(registerUser.email);
    const captcha = await this.redisService.get(
      `captcha_${registerUser.email}`,
    );
    console.log(captcha);
    if (!captcha) {
      throw new HttpException('验证码已过期', HttpStatus.BAD_REQUEST);
    }
    if (captcha !== registerUser.captcha) {
      throw new HttpException('验证码错误', HttpStatus.BAD_REQUEST);
    }
    const foundUser = await this.userRepository.findOneBy({
      username: registerUser.username,
    });
    if (foundUser) {
      throw new HttpException('用户已存在', HttpStatus.BAD_REQUEST);
    }
    const user = new User();
    user.username = registerUser.username;
    user.email = registerUser.email;
    user.nickName = registerUser.nickName;
    user.password = md5(registerUser.password);
    try {
      await this.userRepository.save(user);
      return '注册成功';
    } catch (e) {
      return '注册失败';
    }
    // return 'success';
  }

  async initData() {
    const user1 = new User();
    user1.username = 'zhangsan';
    user1.password = md5('111111');
    user1.email = 'xxx@xx.com';
    user1.isAdmin = true;
    user1.nickName = '张三';

    const user2 = new User();
    user2.username = 'lisi';
    user2.password = md5('222222');
    user2.email = 'yy@yy.com';
    user2.nickName = '李四';

    const role1 = new Role();
    role1.name = '管理员';

    const role2 = new Role();
    role2.name = '普通用户';

    const permission1 = new Permission();
    permission1.code = 'ccc';
    permission1.description = '访问 ccc 接口';

    const permission2 = new Permission();
    permission2.code = 'ddd';
    permission2.description = '访问 ddd 接口';

    user1.roles = [role1];
    user2.roles = [role2];

    role1.permissions = [permission1, permission2];
    role2.permissions = [permission1];

    await this.permissionRepository.save([permission1, permission2]);
    await this.roleRepository.save([role1, role2]);
    await this.userRepository.save([user1, user2]);
  }

  async login(loginUserDto: LoginUserDto, isAdmin: boolean) {
    const user = await this.userRepository.findOne({
      where: {
        username: loginUserDto.username,
        isAdmin,
      },
      relations: ['roles', 'roles.permissions'],
    });
    if (!user) {
      throw new HttpException('用户不存在', HttpStatus.BAD_REQUEST);
    }
    if (user.password !== md5(loginUserDto.password)) {
      throw new HttpException('密码错误', HttpStatus.BAD_REQUEST);
    }
    const vo = new LoginUserVo();
    vo.userInfo = {
      id: user.id,
      username: user.username,
      nickName: user.nickName,
      email: user.email,
      headPic: user.headPic,
      phoneNumber: user.phoneNumber,
      isFrozen: user.isFrozen,
      isAdmin: user.isAdmin,
      createTime: user.createTime,
      roles: user.roles.map((role) => role.name),
      permissions: user.roles.reduce((acc, cur) => {
        cur.permissions.forEach((permission) => {
          if (!acc.includes(permission.code)) {
            acc.push(permission.code);
          }
        });
        return acc;
      }, []),
    };

    return vo;
  }

  async findUserById(id: number, isAdmin: boolean) {
    const user = await this.userRepository.findOne({
      where: { id, isAdmin },
      relations: ['roles', 'roles.permissions'],
    });
    return {
      id: user.id,
      username: user.username,
      email: user.email,
      isAdmin: user.isAdmin,
      roles: user.roles.map((role) => role.name),
      permissions: user.roles.reduce((acc, cur) => {
        cur.permissions.forEach((permission) => {
          if (!acc.includes(permission.code)) {
            acc.push(permission.code);
          }
        });
        return acc;
      }, []),
    };
  }

  async findUserDetailById(userId: number) {
    const user = await this.userRepository.findOne({
      where: {
        id: userId,
      },
    });
    return user;
  }

  async updatePassword(dto: UpdateUserPasswordDto) {
    const captcha = await this.redisService.get(`update_password_${dto.email}`);
    if (!captcha) {
      throw new HttpException('验证码已过期', 400);
    }
    if (captcha !== dto.captcha) {
      throw new HttpException('验证码错误', 400);
    }
    try {
      const user = await this.userRepository.findOne({
        where: {
          username: dto.username,
        },
      });
      if (!user) {
        throw new HttpException('用户名错误', HttpStatus.BAD_REQUEST);
      }
      if (user.email !== dto.email) {
        throw new HttpException('邮箱不正确', HttpStatus.BAD_REQUEST);
      }
      user.password = md5(dto.password);
      await this.userRepository.save(user);
      return '修改密码成功';
    } catch (e) {
      return '修改密码失败';
    }
  }

  async update(userId, updateUserDto: UpdateUserDto) {
    const captcha = await this.redisService.get(
      `update_user_${updateUserDto.email}`,
    );
    if (!captcha) {
      throw new HttpException('验证码已过期', 400);
    }
    if (captcha !== updateUserDto.captcha) {
      throw new HttpException('验证码错误', 400);
    }
    try {
      const user = await this.userRepository.findOne({
        where: {
          id: userId,
        },
      });
      if (updateUserDto.headPic) {
        user.headPic = updateUserDto.headPic;
      }
      if (updateUserDto.nickName) {
        user.nickName = updateUserDto.nickName;
      }
      await this.userRepository.save(user);
      return '修改成功';
    } catch (e) {
      throw new HttpException('修改失败', 400);
    }
  }

  async freezeUserById(userId: number) {
    return await this.userRepository.update(userId, {
      isFrozen: true,
    });
  }

  async findUsersByPage(
    pageNumber: number,
    pageSize: number,
    username: string,
    nickName: string,
    email: string,
  ) {
    const condition: Record<string, any> = {};
    if (username) {
      condition.username = Like(`%${username}%`);
    }
    if (nickName) {
      condition.nickName = Like(`%${nickName}%`);
    }
    if (email) {
      condition.email = Like(`%${email}%`);
    }
    const [users, count] = await this.userRepository.findAndCount({
      select: [
        'id',
        'username',
        'nickName',
        'email',
        'headPic',
        'phoneNumber',
        'isFrozen',
        'createTime',
      ],
      skip: (pageNumber - 1) * pageSize,
      take: pageSize,
      where: condition,
    });
    return {
      users,
      count,
    };
  }
}
